package cn.openea.perpartner.meily.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.openea.perpartner.common.core.constant.Constants;
import cn.openea.perpartner.common.core.exception.ServiceException;
import cn.openea.perpartner.common.core.text.Convert;
import cn.openea.perpartner.common.redis.service.RedisCache;
import cn.openea.perpartner.meily.util.UserContext;
import cn.openea.perpartner.meily.web.entity.Job;
import cn.openea.perpartner.meily.web.entity.dto.JobDto;
import cn.openea.perpartner.meily.web.entity.vo.JobVo;
import cn.openea.perpartner.meily.web.mapper.JobMapper;
import cn.openea.perpartner.meily.web.service.IJobService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author Weird077
 * @description TODO
 * @date 2023-01-06 15:26
 */
@Service
public class JobServiceImpl extends ServiceImpl<JobMapper, Job> implements IJobService {
    @Autowired
    private RedisCache redisCache;
    @Value("${meily.redis.expire.config}")
    private long expireTime;
    private static final String HOT_KEY = "recruit.hot";
    private static final String TOP_LIST = "recruit.top5.list";

    @Override
    public List<Job> selectList(JobVo vo) {
        LambdaQueryWrapper<Job> wrapper = new LambdaQueryWrapper<>();

        // 岗位名称
        if (StrUtil.isNotBlank(vo.getJobName())) {
            wrapper.like(Job::getJobName, vo.getJobName());
        }

        // 状态。招聘中、停止招聘
        if (StrUtil.isNotBlank(vo.getStatus())) {
            wrapper.eq(Job::getStatus, vo.getStatus());
        }

        // 创建时间（区间搜索）
        String dateRange = vo.getDateRange();
        if (JSONUtil.isJson(dateRange)) {
            JSONObject jsonObject = JSONObject.parseObject(dateRange);
            String startDate = jsonObject.getString("startDate");
            String endDate = jsonObject.getString("endDate");
            if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
                // 比较两个时间的大小
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                if (LocalDate.parse(startDate, formatter).isAfter(LocalDate.parse(endDate, formatter))) {
                    throw new ServiceException("结束时间不能大于开始时间");
                }
                wrapper.apply("DATE(create_time) BETWEEN '" + startDate + "' AND '" + endDate + "'");
            }
        }

        // 关键字搜索
        String searchStr = vo.getSearchStr();
        if (StrUtil.isNotBlank(searchStr)) {
            wrapper.and(wrap -> wrap.like(Job::getJobName, searchStr)
                    .or().like(Job::getKeyword, searchStr)
                    .or().like(Job::getRecruits, searchStr)
                    .or().like(Job::getSalary, searchStr)
                    .or().like(Job::getExperiece, searchStr)
                    .or().like(Job::getDegree, searchStr)
                    .or().like(Job::getType, searchStr)
                    .or().like(Job::getRequirements, searchStr)
                    .or().like(Job::getCompany, searchStr)
                    .or().like(Job::getArea, searchStr)
                    .or().like(Job::getAddress, searchStr)
                    .or().like(Job::getDetails, searchStr)
                    .or().like(Job::getJobTags, searchStr));
        }

        wrapper.orderByDesc(Job::getJobTop);
        wrapper.orderByDesc(Job::getCreateTime);
        return list(wrapper);
    }

    /**
     * 分页查询-小程序
     * @param vo
     * @return
     */
    @Override
    public List<Job> queryAll(JobVo vo) {
        LambdaQueryWrapper<Job> wrapper = new LambdaQueryWrapper<>();

        // 只获取状态为“招聘中”的数据
        wrapper.eq(Job::getStatus, "招聘中");

        // 工作要求。远程、坐班、外勤
        if (StrUtil.isNotBlank(vo.getRequirements())) {
            wrapper.eq(Job::getRequirements, vo.getRequirements());
        }

        // 关键字搜索
        String searchStr = vo.getSearchStr();
        if (StrUtil.isNotBlank(searchStr)) {
            wrapper.and(wrap -> wrap.like(Job::getJobName, searchStr)
                    .or().like(Job::getKeyword, searchStr)
                    .or().like(Job::getRecruits, searchStr)
                    .or().like(Job::getSalary, searchStr)
                    .or().like(Job::getExperiece, searchStr)
                    .or().like(Job::getDegree, searchStr)
                    .or().like(Job::getType, searchStr)
                    .or().like(Job::getRequirements, searchStr)
                    .or().like(Job::getCompany, searchStr)
                    .or().like(Job::getArea, searchStr)
                    .or().like(Job::getAddress, searchStr)
                    .or().like(Job::getDetails, searchStr)
                    .or().like(Job::getJobTags, searchStr));
        }

        wrapper.orderByDesc(Job::getJobTop);
        wrapper.orderByDesc(Job::getCreateTime);

        return list(wrapper);
    }

    @Override
    public boolean insert(Job job) {
        job.setCreateUser(UserContext.getUserId());
        job.setUpdateUser(UserContext.getUserId());
        String key = getCacheKey(HOT_KEY);
        redisCache.setCacheObject(key, job.getJobName());
        redisCache.expire(key, expireTime, TimeUnit.MINUTES);
        redisCache.deleteObject(getCacheKey(TOP_LIST));
        return save(job);
    }

    @Override
    public Job selectHotJob() {
        String key = getCacheKey(HOT_KEY);
        Job job = redisCache.getCacheObject(key);
        if (BeanUtil.isEmpty(job)) {
            LambdaQueryWrapper<Job> wrapper = new LambdaQueryWrapper<>();
            wrapper.orderByDesc(Job::getCreateTime);
            wrapper.last("limit 1");
            job = getOne(wrapper);
            redisCache.setCacheObject(key, job);
            redisCache.expire(key, expireTime, TimeUnit.MINUTES);
        }
        return job;
    }

    @Override
    public List<Job> topList() {
        String key = getCacheKey(TOP_LIST);
        List<Job> list = redisCache.getCacheList(key);
        if (!list.isEmpty()) {
            return list;
        }
        LambdaQueryWrapper<Job> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Job::getStatus, "招聘中");
        wrapper.orderByDesc(Job::getCreateTime);
        wrapper.last("limit 5");
        list = list(wrapper);
        if (!list.isEmpty()) {
            redisCache.setCacheList(key, list);
            redisCache.expire(key, expireTime, TimeUnit.MINUTES);
        }
        return list;
    }

    @Override
    public JobDto getContactById(Long id) {
        Job job = getById(id);
        JobDto jobDto = new JobDto();
        if (BeanUtil.isEmpty(job)) {
            BeanUtil.copyProperties(job, jobDto);
        }
        return jobDto;
    }

    @Override
    public boolean delete(List<Long> idList) {
        redisCache.deleteObject(getCacheKey(HOT_KEY));
        redisCache.deleteObject(getCacheKey(TOP_LIST));
        return removeBatchByIds(idList);
    }

    @Override
    public boolean copy(Long id) {
        Job job = getById(id);
        if (BeanUtil.isNotEmpty(job)) {
            Job copy = new Job();
            BeanUtil.copyProperties(job, copy, "jobId");
            copy.setJobName(job.getJobName() + "_copy");
            return save(copy);
        }
        return false;
    }

    @Override
    public String importData(List<Job> jobList) {
        if (jobList.isEmpty()) {
            throw new ServiceException("导入数据不能为空！");
        }
        for (Job job : jobList) {
            job.setStatus("未发布");
            job.setCreateUser(UserContext.getUserId());
            job.setUpdateUser(UserContext.getUserId());
        }
        boolean isSuccess = saveBatch(jobList);
        return isSuccess ? "导入成功！" : "导入失败";
    }

    @Override
    public boolean top(Long jobId) {
        LambdaQueryWrapper<Job> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(Job::getJobTop);
        wrapper.last("limit 1");
        Job topJob = this.getOne(wrapper);
        if (BeanUtil.isEmpty(topJob)) {
            topJob.setJobTop("0");
        }
        if (StrUtil.isEmpty(topJob.getJobTop())) {
            topJob.setJobTop("0");
        }
        int sort = Convert.toInt(topJob.getJobTop());
        sort++;
        Job job = getById(jobId);
        job.setJobTop(Convert.toStr(sort));
        job.setUpdateUser(UserContext.getUserId());
        return updateById(job);
    }

    @Override
    public boolean topCancel(Long jobId) {
        Job job = getById(jobId);
        job.setJobTop("");
        job.setUpdateUser(UserContext.getUserId());
        return updateById(job);
    }

    @Override
    public boolean stopHire(Long jobId) {
        Job job = getById(jobId);
        job.setStatus("停止招聘");
        job.setUpdateUser(UserContext.getUserId());
        return updateById(job);
    }

    @Override
    public boolean republish(Long jobId) {
        Job job = getById(jobId);
        job.setStatus("招聘中");
        job.setUpdateUser(UserContext.getUserId());
        return updateById(job);
    }


    private String getCacheKey(String configKey) {
        return Constants.MERRY_CONFIG_KEY + configKey;
    }
}
